package com.ys.erp.stage_marketing_service.service;

import cn.hutool.core.io.IoUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.enums.EnableEnum;
import com.ys.erp.common.enums.RedisKey;
import com.ys.erp.common.enums.old.StatusOldEnum;
import com.ys.erp.common.enums.old.TypeOldEnum;
import com.ys.erp.common.util.DateUtil;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.*;
import com.ys.erp.entity.service.*;
import com.ys.erp.framework.bean.dto.StageEmpDTO;
import com.ys.erp.framework.exception.YsException;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.framework.response.ResponseDTO;
import com.ys.erp.stage_marketing_service.bean.condition.ActivityTurntableCondition;
import com.ys.erp.stage_marketing_service.bean.dto.ActivityTurntableJoinPageExcelDTO;
import com.ys.erp.stage_marketing_service.bean.vo.*;
import jakarta.servlet.http.HttpServletResponse;
import com.ys.erp.stage_marketing_service.utils.WxUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @author 南山
 * @date 2025/09/19 17:41
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ActivityTurntableService {
    private final IActivityTurnableService iActivityTurnableService;
    private final IActivityTurntablePrizedService iActivityTurntablePrizedService;
    private final IActivityTurntableJoinLogService iActivityTurntableJoinLogService;
    private final IActivityTurnableRedeemRecordService iActivityTurnableRedeemRecordService;
    private final IUserService iUserService;
    private final RedisTemplate<String, Long> redisTemplateLong;
    private final IUserCatService iUserCatService;
    private final IGoodsService iGoodsService;
    private final IGoodsSpecsService iGoodsSpecsService;
    @Value("${properties.freight.app-id}")
    private String freightAppId;
    private final WxUtil wxUtil;


    public PageDTO<ActivityTurntableVO> getActivityTurntablePage(StageEmpDTO emp, ActivityTurntableCondition.PageActivityTurntableCon con) {
        Page<ActivityTurnable> page = iActivityTurnableService.page(new Page<>(con.getCurrent(), con.getSize()), new QueryWrapper<ActivityTurnable>().lambda().orderByDesc(ActivityTurnable::getCreateTime));
        if (page.getRecords().isEmpty()) {
            return new PageDTO<>(page.getCurrent(), page.getTotal(), new ArrayList<>());
        }
        List<ActivityTurnable> records = page.getRecords();
        List<Long> turnableIdList = records.stream().map(ActivityTurnable::getId).toList();

        QueryWrapper<ActivityTurntablePrized> prizedQw = new QueryWrapper<>();
        prizedQw.lambda().in(ActivityTurntablePrized::getActivityId, turnableIdList);
        Map<Long, List<ActivityTurntablePrized>> prizedListMap = iActivityTurntablePrizedService.list(prizedQw).stream()
                .collect(Collectors.groupingBy(ActivityTurntablePrized::getActivityId));
        QueryWrapper<ActivityTurntableJoinLog> joinLogQw = new QueryWrapper<>();
        joinLogQw.lambda().in(ActivityTurntableJoinLog::getActivityId, turnableIdList);
        Map<Long, List<ActivityTurntableJoinLog>> joinLogUserListMap = iActivityTurntableJoinLogService.list(joinLogQw).stream()
                .collect(Collectors.groupingBy(ActivityTurntableJoinLog::getActivityId));
        QueryWrapper<ActivityTurnableRedeemRecord> redeemRecordQw = new QueryWrapper<>();
        redeemRecordQw.lambda().in(ActivityTurnableRedeemRecord::getActivityId, turnableIdList);
        List<ActivityTurnableRedeemRecord> redeemRecordUserList = iActivityTurnableRedeemRecordService.list(redeemRecordQw);
        Map<Long, List<ActivityTurnableRedeemRecord>> redeemRecordListMap = redeemRecordUserList.stream()
                .collect(Collectors.groupingBy(ActivityTurnableRedeemRecord::getActivityId));
        ArrayList<ActivityTurntableVO> results = new ArrayList<>();
        for (ActivityTurnable record : records) {
            ActivityTurntableVO vo = new ActivityTurntableVO();
            vo.setId(record.getId());
            vo.setActivityName(record.getActivityName());
            vo.setActivityTime("开始：" + DateUtil.localDateTimeFormat(record.getStartTime())
                    + System.lineSeparator()
                    + "结束：" + DateUtil.localDateTimeFormat(record.getEndTime()));
            List<ActivityTurntablePrized> turntablePrizedList = prizedListMap.get(record.getId());
            if (CollectionUtils.isEmpty(turntablePrizedList)) {
                //不会出现没有商品的转盘
                continue;
            }
            vo.setPrizedNum(turntablePrizedList.size());
            vo.setActivityRule(getActivityTurntableRule(record));
            List<ActivityTurntableJoinLog> joinLogList = joinLogUserListMap.get(record.getId());
            if (CollectionUtils.isEmpty(joinLogList)) {
                vo.setJoinNum(0);
            } else {
                Set<Long> joinLogUserIdList = joinLogList.stream().map(ActivityTurntableJoinLog::getUserId).collect(Collectors.toSet());
                vo.setJoinNum(joinLogUserIdList.size());
            }
            List<ActivityTurnableRedeemRecord> redeemRecordList = redeemRecordListMap.get(record.getId());

            if (CollectionUtils.isEmpty(redeemRecordList)) {
                vo.setRedeemNum(0);
                vo.setWinnerNum(0);
            } else {
                Set<Long> redeemRecordUserIdList = redeemRecordList.stream().map(ActivityTurnableRedeemRecord::getUserId).collect(Collectors.toSet());

                vo.setWinnerNum(redeemRecordUserIdList.size());
                int redeemNum = 0, physicalRedeemNum = 0;
                for (ActivityTurnableRedeemRecord activityTurnableRedeemRecord : redeemRecordList) {
                    if (!activityTurnableRedeemRecord.getRedeemStatus().equals(ActivityTurnableRedeemRecord.Enums.ISSUED.name())) {
                        continue;
                    }
                    redeemNum++;
                    if (activityTurnableRedeemRecord.getType().equals(EnableEnum.NO.getEnable())) {
                        continue;
                    }
                    physicalRedeemNum++;

                }
                vo.setRedeemNum(redeemNum);
                vo.setPhysicalRedeemNum(physicalRedeemNum);
            }
            vo.setActivityStatus(ActivityTurnable.ENUM_MAP.get(record.getActivityStatus()));
            results.add(vo);
        }
        YsThread.execute(() -> {
            List<ActivityTurnable> activityTurnableList = page.getRecords();
            for (ActivityTurnable activityTurnable : activityTurnableList) {
                int timePosition = DateUtil.getTimePosition(LocalDateTime.now(), activityTurnable.getStartTime(), activityTurnable.getEndTime());
                if (timePosition == 0) {
                    activityTurnable.setActivityStatus(ActivityTurnable.Enums.NOT_STARTED.name());
                }
                if (timePosition == 2) {
                    activityTurnable.setActivityStatus(ActivityTurnable.Enums.ENDED.name());
                }
                if (timePosition == 1) {
                    activityTurnable.setActivityStatus(ActivityTurnable.Enums.ONGOING.name());
                }
            }
            iActivityTurnableService.updateBatchById(activityTurnableList);
            log.info("更新转盘活动状态成功");
        });
        return new PageDTO<>(page.getCurrent(), page.getTotal(), results);
    }


    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdateActivityTurntable(StageEmpDTO emp, ActivityTurntableCondition.AddOrUpdateActivityTurntableCon con) {
        YsThread.execute(() -> {
            ActivityTurnable turnable;
            if (Objects.isNull(con.getId())) {
                turnable = new ActivityTurnable();
            } else {
                turnable = iActivityTurnableService.getById(con.getId());
            }
            BeanUtils.copyProperties(con, turnable);
            turnable.setStartTime(DateUtil.stringToLocalDateTime(con.getStartTime()));
            turnable.setEndTime(DateUtil.stringToLocalDateTime(con.getEndTime()));
            int timePosition = DateUtil.getTimePosition(LocalDateTime.now(), turnable.getStartTime(), turnable.getEndTime());
            if (timePosition == 0) {
                turnable.setActivityStatus(ActivityTurnable.Enums.NOT_STARTED.name());
            }
            if (timePosition == 1) {
                turnable.setActivityStatus(ActivityTurnable.Enums.ONGOING.name());
            }
            if (timePosition == 2) {
                turnable.setActivityStatus(ActivityTurnable.Enums.ENDED.name());
            }
            setRule(con, turnable);
            iActivityTurnableService.saveOrUpdate(turnable);
            setActivityTurntablePrized(con, turnable);
        });

    }


    public ActivityTurntableInfoVO getActivityTurntableInfo(StageEmpDTO emp, Long activityId) {
        ActivityTurnable turnable = iActivityTurnableService.getById(activityId);
        if (Objects.isNull(turnable)) {
            throw new YsException(-1, "该转盘不存在");
        }
        ActivityTurntableInfoVO vo = new ActivityTurntableInfoVO();
        vo.setActivityName(turnable.getActivityName());
        vo.setStartTime(DateUtil.localDateTimeFormat(turnable.getStartTime()));
        vo.setEndTime(DateUtil.localDateTimeFormat(turnable.getEndTime()));
        vo.setBackground(turnable.getBackground());
        vo.setExhaustMessage(turnable.getExhaustMessage());
        vo.setShareIcon(turnable.getShareIcon());
        vo.setMyPrizeNameIcon(turnable.getMyPrizeNameIcon());
        vo.setSharePoster(turnable.getSharePoster());
        ActivityTurntableInfoVO.JoinRule joinRule = new ActivityTurntableInfoVO.JoinRule();
        joinRule.setType(turnable.getJoinRuleDTO().getType());
        joinRule.setSiphonList(turnable.getJoinRuleDTO().getSiphonList().stream().map(siphon -> {
            ActivityTurntableInfoVO.Siphon v = new ActivityTurntableInfoVO.Siphon();
            v.setType(siphon.getType());
            v.setNum(siphon.getNum());
            return v;
        }).toList());
        vo.setJoinRule(joinRule);
        ActivityTurntableInfoVO.RedeemRule redeemRule = new ActivityTurntableInfoVO.RedeemRule();
        redeemRule.setType(turnable.getRedeemRuleDTO().getType());
        redeemRule.setHour(turnable.getRedeemRuleDTO().getHour());
        vo.setRedeemRule(redeemRule);
        QueryWrapper<ActivityTurntablePrized> prizedQw = new QueryWrapper<>();
        prizedQw.lambda().eq(ActivityTurntablePrized::getActivityId, turnable.getId());
        List<ActivityTurntablePrized> prizedList = iActivityTurntablePrizedService.list(prizedQw);
        vo.setActivityTurntablePrizedList(prizedList.stream().map(prized -> {
            ActivityTurntableInfoVO.ActivityTurntablePrized activityTurntablePrizedVO = new ActivityTurntableInfoVO.ActivityTurntablePrized();
            activityTurntablePrizedVO.setPrizedName(prized.getPrizedName());
            activityTurntablePrizedVO.setPrizedIcon(prized.getPrizedIcon());
            activityTurntablePrizedVO.setPrizedId(prized.getPrizedId());
            activityTurntablePrizedVO.setType(prized.getType());
            if (prized.getType().equals(ActivityTurntablePrized.Enums.YS_MONEY.name())) {
                activityTurntablePrizedVO.setQuantityPerPrize(MoneyUtil.long2Str(prized.getQuantityPerPrize()));
                activityTurntablePrizedVO.setTotal(MoneyUtil.long2Str(prized.getTotal()));

            } else {
                activityTurntablePrizedVO.setQuantityPerPrize(prized.getQuantityPerPrize().toString());
                activityTurntablePrizedVO.setTotal(prized.getTotal().toString());
            }

            activityTurntablePrizedVO.setWinnerRate(prized.getWinnerRate());
            return activityTurntablePrizedVO;
        }).toList());
        return vo;
    }

    public ActivityTurntableUrlVO getActivityTurntableUrl(StageEmpDTO emp, Long activityId) {
        ActivityTurnable turnable = iActivityTurnableService.getById(activityId);
        if (Objects.isNull(turnable)) {
            throw new YsException(-1, "该转盘不存在");
        }
        ActivityTurntableUrlVO vo = new ActivityTurntableUrlVO();
        if (StringUtils.isBlank(turnable.getQrCodeUrl())) {
            String param = "activityId=" + activityId;
            String qrCodeUrl = wxUtil.turntableQrCode(param, "cat-package/pages/lottery/index");
            turnable.setQrCodeUrl(qrCodeUrl);
            iActivityTurnableService.updateById(turnable);
            vo.setQrCodeUrl(qrCodeUrl);
        } else {
            vo.setQrCodeUrl(turnable.getQrCodeUrl());
        }
        vo.setUrl("/cat-package/pages/lottery/index?activityId=" + activityId);
        return vo;
    }

    public void stopActivityTurntable(StageEmpDTO emp, Long activityId) {
        YsThread.execute(() -> {
            ActivityTurnable turnable = iActivityTurnableService.getById(activityId);
            if (Objects.isNull(turnable)) {
                throw new YsException(-1, "该转盘不存在");
            }
            turnable.setActivityStatus(ActivityTurnable.Enums.ENDED.name());
            iActivityTurnableService.updateById(turnable);
            QueryWrapper<ActivityTurntablePrized> prizedQw = new QueryWrapper<>();
            prizedQw.lambda().eq(ActivityTurntablePrized::getActivityId, turnable.getId());
            List<ActivityTurntablePrized> prizedList = iActivityTurntablePrizedService.list();
            for (ActivityTurntablePrized activityTurntablePrized : prizedList) {
                redisTemplateLong.delete(MessageFormat.format(RedisKey.Enums.ACTIVITY_TURNTABLE_PRIZED_KEY.getKey(), activityTurntablePrized.getId()));
            }
        });
    }

    public ActivityTurntableJoinVo getActivityTurntableJoin(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntableJoinUserPage con) {
        QueryWrapper<ActivityTurntableJoinLog> joinLogQw = new QueryWrapper<>();
        joinLogQw.lambda().eq(ActivityTurntableJoinLog::getActivityId, con.getActivityId());
        joinLogQw.lambda().select(ActivityTurntableJoinLog::getUserId);
        List<ActivityTurntableJoinLog> joinLogList = iActivityTurntableJoinLogService.list(joinLogQw);
        Set<Long> userIdList = joinLogList.stream().map(ActivityTurntableJoinLog::getUserId).collect(Collectors.toSet());
        List<User> users = iUserService.listByIds(userIdList);
        QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
        userCatQw.lambda().in(UserCat::getUserId, userIdList);
        List<UserCat> userCatList = iUserCatService.list(userCatQw);
        Map<Long, List<UserCat>> userCatMap = userCatList.stream().collect(Collectors.groupingBy(UserCat::getUserId));

        ActivityTurntableJoinVo vo = new ActivityTurntableJoinVo();

        userCatList.stream()
                .filter(it -> StringUtils.isNotBlank(it.getUserFeeRemark()))
                .collect(Collectors.groupingBy(UserCat::getUserFeeRemark, Collectors.counting()))
                .entrySet().stream().max(Map.Entry.comparingByValue()).map(it -> {
                    vo.setMaxUserTakeMethodName(it.getKey());
                    return vo;
                });
        System.out.println(userCatList.stream().filter(it -> StringUtils.isNotBlank(it.getUserFeeRemark()))
                .filter(it -> it.getUserFeeRemark().equals(vo.getMaxUserTakeMethodName())).collect(Collectors.toSet()).size());
        vo.setMaxUserTakeMethodNum(userCatList.stream().filter(it -> StringUtils.isNotBlank(it.getUserFeeRemark()))
                .filter(it -> it.getUserFeeRemark().equals(vo.getMaxUserTakeMethodName())).map(UserCat::getUserId).collect(Collectors.toSet()).size());

        HashSet<Long> takePet = new HashSet<>();
        HashSet<Long> buyPet = new HashSet<>();
        HashSet<Long> notPet = new HashSet<>();
        HashSet<Long> returnPet = new HashSet<>();


        HashSet<User> userSet = new HashSet<>(users);
        for (User user : userSet) {
            List<UserCat> userCats = userCatMap.get(user.getId());
            if (CollectionUtils.isEmpty(userCats)) {
                notPet.add(user.getId());
                continue;
            }
            for (UserCat userCat : userCats) {
                if (Objects.isNull(userCat.getCatStatus())) {
                    continue;
                }
                if (userCat.getCatStatus() == StatusOldEnum.USER_CAT_RETURN_ORDER.getStatus()) {
                    returnPet.add(user.getId());
                    continue;
                }
                if (!userCat.getCatStatus().equals(StatusOldEnum.USER_CAT_TAKE.getStatus())) {
                    continue;
                }
                takePet.add(user.getId());
                if (!userCat.getContractType().equals(TypeOldEnum.CAT_CONTRACT_BUY.getType())) {
                    continue;
                }
                buyPet.add(user.getId());
            }
        }

        vo.setJoinTotalNum(userIdList.size());
        vo.setTakePet(takePet.size());
        vo.setBuyPet(buyPet.size());
        vo.setNotPet(notPet.size());
        vo.setReturnPet(returnPet.size());
        return vo;
    }

    public PageDTO<ActivityTurntableJoinUserVO> getActivityTurntableJoinUserPage(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntableJoinUserPage con) {
        Set<Long> joinLogUserIdList = iActivityTurntableJoinLogService.list(new QueryWrapper<ActivityTurntableJoinLog>().lambda()
                        .eq(ActivityTurntableJoinLog::getActivityId, con.getActivityId()).select(ActivityTurntableJoinLog::getUserId)).stream()
                .map(ActivityTurntableJoinLog::getUserId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(joinLogUserIdList)) {
            return new PageDTO<>(0L, 0L, new ArrayList<>());
        }
        QueryWrapper<User> userQw = new QueryWrapper<>();
        if (StringUtils.isNotBlank(con.getPetTakeStatus())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            if ("NOT_ADOPT".equals(con.getPetTakeStatus())) {
                userCatQw.lambda().select(UserCat::getUserId);
                userCatQw.lambda().in(UserCat::getUserId, joinLogUserIdList);
                List<Long> userIdList = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).toList();
                if (CollectionUtils.isEmpty(userIdList)) {
                    userQw.lambda().notIn(User::getId, "-1");
                } else {
                    userQw.lambda().notIn(User::getId, userIdList);
                }
            }
            if ("ADOPT".equals(con.getPetTakeStatus())) {
                userCatQw.lambda().select(UserCat::getUserId);
                userCatQw.lambda().in(UserCat::getUserId, joinLogUserIdList);
                userCatQw.lambda().eq(UserCat::getCatStatus, StatusOldEnum.USER_CAT_TAKE.getStatus());
                List<Long> userIdList = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).toList();
                if (CollectionUtils.isEmpty(userIdList)) {
                    userQw.lambda().in(User::getId, -1);
                } else {
                    userQw.lambda().in(User::getId, userIdList);
                }
            }

            if ("BUY".equals(con.getPetTakeStatus())) {
                userCatQw.lambda().select(UserCat::getUserId);
                userCatQw.lambda().in(UserCat::getUserId, joinLogUserIdList);
                userCatQw.lambda().eq(UserCat::getCatStatus, StatusOldEnum.USER_CAT_TAKE.getStatus());
                userCatQw.lambda().eq(UserCat::getContractType, TypeOldEnum.CAT_CONTRACT_BUY.getType());
                List<Long> userIdList = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).toList();
                if (CollectionUtils.isEmpty(userIdList)) {
                    userQw.lambda().in(User::getId, -1);
                } else {
                    userQw.lambda().in(User::getId, userIdList);
                }
            }
            if ("RETURN".equals(con.getPetTakeStatus())) {
                userCatQw.lambda().select(UserCat::getUserId);
                userCatQw.lambda().eq(UserCat::getCatStatus, StatusOldEnum.USER_CAT_RETURN_ORDER.getStatus());
                List<Long> userIdList = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).toList();
                if (CollectionUtils.isEmpty(userIdList)) {
                    userQw.lambda().in(User::getId, -1);
                } else {
                    userQw.lambda().in(User::getId, userIdList);
                }
            }
        }
        QueryWrapper<ActivityTurntableJoinLog> joinLogQw = new QueryWrapper<>();
        joinLogQw.lambda().select(ActivityTurntableJoinLog::getUserId);
        joinLogQw.lambda().eq(ActivityTurntableJoinLog::getActivityId, con.getActivityId());
        List<Long> joinUserIdList = iActivityTurntableJoinLogService.list(joinLogQw).stream().map(ActivityTurntableJoinLog::getUserId).toList();
        userQw.lambda().in(User::getId, joinUserIdList);

        Page<User> page = iUserService.page(new Page<>(con.getCurrent(), con.getSize()), userQw);
        List<User> records = page.getRecords();

        if (records.isEmpty()) {
            return new PageDTO<>(page.getCurrent(), page.getTotal(), new ArrayList<>());
        }

        List<Long> userIdList = records.stream().map(User::getId).toList();
        CompletableFuture<Map<Long, List<ActivityTurntableJoinLog>>> joinLogMapFuture = YsThread.execute(() -> {
            joinLogQw.clear();
            joinLogQw.lambda().eq(ActivityTurntableJoinLog::getActivityId, con.getActivityId());
            joinLogQw.lambda().in(ActivityTurntableJoinLog::getUserId, userIdList);
            List<ActivityTurntableJoinLog> turntableJoinLogList = iActivityTurntableJoinLogService.list(joinLogQw);
            return turntableJoinLogList.stream()
                    .collect(Collectors.groupingBy(ActivityTurntableJoinLog::getUserId));
        });


        CompletableFuture<Map<Long, Long>> redeemRecordMapFuture = YsThread.execute(() -> {
            QueryWrapper<ActivityTurnableRedeemRecord> redeemRecordQw = new QueryWrapper<>();
            redeemRecordQw.lambda().in(ActivityTurnableRedeemRecord::getUserId, userIdList);
            List<ActivityTurnableRedeemRecord> redeemRecordList = iActivityTurnableRedeemRecordService.list(redeemRecordQw);
            return redeemRecordList.stream().collect(Collectors.groupingBy(ActivityTurnableRedeemRecord::getUserId, Collectors.counting()));
        });
        CompletableFuture<Set<Long>> userIdSetFuture = YsThread.execute(() -> {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().in(UserCat::getUserId, userIdList);
            userCatQw.lambda().eq(UserCat::getCatStatus, StatusOldEnum.USER_CAT_TAKE.getStatus());
            List<UserCat> userCatList = iUserCatService.list(userCatQw);
            return userCatList.stream().map(UserCat::getUserId).collect(Collectors.toSet());
        });


        Map<Long, Long> redeemListMap = redeemRecordMapFuture.join();
        Set<Long> userIdSet = userIdSetFuture.join();

        Map<Long, List<ActivityTurntableJoinLog>> joinLogMap = joinLogMapFuture.join();
        ArrayList<ActivityTurntableJoinUserVO> results = new ArrayList<>();
        for (User record : records) {
            ActivityTurntableJoinUserVO turntableJoinUserVO = new ActivityTurntableJoinUserVO();
            turntableJoinUserVO.setUserId(record.getId());
            turntableJoinUserVO.setPetNickName(record.getNickName());
            turntableJoinUserVO.setPic(record.getAvatar());
            List<ActivityTurntableJoinLog> joinLogList = joinLogMap.get(record.getId());
            ActivityTurntableJoinLog newJoinLog = joinLogList.stream()
                    .sorted(Comparator.comparing(ActivityTurntableJoinLog::getCreateTime).reversed()).toList().getFirst();
            turntableJoinUserVO.setJoinNum(joinLogList.size());
            turntableJoinUserVO.setNewJoinTime(newJoinLog.getCreateTime());
            turntableJoinUserVO.setWinnerNum(Objects.isNull(redeemListMap.get(record.getId())) ? 0 : Integer.parseInt(redeemListMap.get(record.getId()).toString()));
            turntableJoinUserVO.setIsTakeCat(userIdSet.contains(record.getId()) ? EnableEnum.YES.getEnable() : EnableEnum.NO.getEnable());
            results.add(turntableJoinUserVO);
        }
        return new PageDTO<>(page.getCurrent(), page.getTotal(), results.stream().sorted(Comparator.comparing(ActivityTurntableJoinUserVO::getNewJoinTime).reversed()).toList());
    }

    public List<ActivityTurntableWinnerVO> getActivityTurntableWinner(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntableWinnerPage con) {
        QueryWrapper<ActivityTurnableRedeemRecord> redeemRecordQw = new QueryWrapper<>();
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getActivityId, con.getActivityId());
        List<ActivityTurnableRedeemRecord> redeemRecordList = iActivityTurnableRedeemRecordService.list(redeemRecordQw);
        if (CollectionUtils.isEmpty(redeemRecordList)) {
            return List.of();
        }
        Map<Long, List<ActivityTurnableRedeemRecord>> reedeemPrizedIdMap = redeemRecordList.stream().collect(Collectors.groupingBy(ActivityTurnableRedeemRecord::getPrizedId));
        Set<ActivityTurntablePrized> prizedList = redeemRecordList.stream().map(ActivityTurnableRedeemRecord::getActivityTurntablePrized).collect(Collectors.toSet());
        Map<String, List<ActivityTurntablePrized>> prizedTypeMap = prizedList.stream().filter(it -> Objects.nonNull(it.getType()))
                .collect(Collectors.groupingBy(ActivityTurntablePrized::getType, Collectors.toList()));
        ArrayList<ActivityTurntableWinnerVO> result = new ArrayList<>();
        for (Map.Entry<String, List<ActivityTurntablePrized>> entry : prizedTypeMap.entrySet()) {
            ActivityTurntableWinnerVO vo = new ActivityTurntableWinnerVO();
            vo.setName(ActivityTurntablePrized.ENUM_MAP.get(entry.getKey()) + "中奖人数");
            long winnerNum = 0, redeemNum = 0, totalNum = 0;
            List<ActivityTurntablePrized> value = entry.getValue();
            for (ActivityTurntablePrized activityTurntablePrized : value) {
                List<ActivityTurnableRedeemRecord> redeemRecords = reedeemPrizedIdMap.get(activityTurntablePrized.getId());
                totalNum += redeemRecords.size() * activityTurntablePrized.getQuantityPerPrize();
                redeemNum += redeemRecords.stream()
                        .filter(it -> it.getRedeemStatus().equals(ActivityTurnableRedeemRecord.Enums.ISSUED.name()))
                        .count() * activityTurntablePrized.getQuantityPerPrize();
                winnerNum += redeemRecords.size();
            }
            if (entry.getKey().equals(ActivityTurntablePrized.Enums.YS_MONEY.name())) {
                vo.setTotalNum(MoneyUtil.long2Str(totalNum));
                vo.setRedeemNum(MoneyUtil.long2Str(redeemNum));
            } else {
                vo.setTotalNum(String.valueOf(totalNum));
                vo.setRedeemNum(String.valueOf(redeemNum));
            }
            vo.setWinnerNum(String.valueOf(winnerNum));
            result.add(vo);
        }
        return result;
    }


    public PageDTO<ActivityTurntableWinnerUserVO> getActivityTurntableWinnerPage(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntableWinnerPage con) {
        Set<Long> winnerLogUserIdList = iActivityTurnableRedeemRecordService.list(new QueryWrapper<ActivityTurnableRedeemRecord>().lambda()
                        .eq(ActivityTurnableRedeemRecord::getActivityId, con.getActivityId()).select(ActivityTurnableRedeemRecord::getUserId)).stream()
                .map(ActivityTurnableRedeemRecord::getUserId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(winnerLogUserIdList)) {
            return new PageDTO<>(0L, 0L, new ArrayList<>());
        }
        QueryWrapper<User> userQw = new QueryWrapper<>();
        if (StringUtils.isNotBlank(con.getIsPetTake())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            if (con.getIsPetTake().equals(EnableEnum.YES.name())) {
                userCatQw.lambda().select(UserCat::getUserId);
                userCatQw.lambda().in(UserCat::getUserId, winnerLogUserIdList);
                userCatQw.lambda().eq(UserCat::getCatStatus, StatusOldEnum.USER_CAT_TAKE.getStatus());
                List<Long> userIdList = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).toList();
                userQw.lambda().in(User::getId, userIdList);
            } else {
                userCatQw.lambda().select(UserCat::getUserId);
                userCatQw.lambda().in(UserCat::getUserId, winnerLogUserIdList);
                List<Long> userIdList = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).toList();
                userQw.lambda().notIn(User::getId, userIdList);
            }
        }
        QueryWrapper<ActivityTurnableRedeemRecord> redeemRecordQw = new QueryWrapper<>();
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getActivityId, con.getActivityId());
        List<ActivityTurnableRedeemRecord> reedemmRecordList = iActivityTurnableRedeemRecordService.list(redeemRecordQw);
        Set<Long> redeemRecordUserIdList = reedemmRecordList.stream().
                map(ActivityTurnableRedeemRecord::getUserId).collect(Collectors.toSet());
        Map<Long, List<ActivityTurnableRedeemRecord>> redeemRecordMap = reedemmRecordList.stream()
                .collect(Collectors.groupingBy(ActivityTurnableRedeemRecord::getUserId));
        if (StringUtils.isNotBlank(con.getPrizedType())) {
            Set<Long> prizedIdList = reedemmRecordList.stream()
                    .map(ActivityTurnableRedeemRecord::getActivityTurntablePrized)
                    .filter(prized -> prized.getType().equals(con.getPrizedType())).map(ActivityTurntablePrized::getId)
                    .collect(Collectors.toSet());
            redeemRecordUserIdList = reedemmRecordList.stream()
                    .filter(it -> prizedIdList.contains(it.getPrizedId()))
                    .map(ActivityTurnableRedeemRecord::getUserId)
                    .collect(Collectors.toSet());
        }
        if (StringUtils.isNotBlank(con.getRedeemStatus())) {
            redeemRecordUserIdList = reedemmRecordList.stream()
                    .filter(it -> it.getRedeemStatus().equals(con.getRedeemStatus()))
                    .map(ActivityTurnableRedeemRecord::getUserId)
                    .collect(Collectors.toSet());
        }
        userQw.lambda().in(User::getId, redeemRecordUserIdList);
        Page<User> page = iUserService.page(new Page<>(con.getCurrent(), con.getSize()), userQw);
        List<User> records = page.getRecords();

        if (records.isEmpty()) {
            return new PageDTO<>(page.getCurrent(), page.getTotal(), new ArrayList<>());
        }
        List<Long> userIdList = records.stream().map(User::getId).toList();


        CompletableFuture<Map<Long, List<ActivityTurntableJoinLog>>> joinLogMapFuture = YsThread.execute(() -> {
            QueryWrapper<ActivityTurntableJoinLog> joinLogQw = new QueryWrapper<>();
            joinLogQw.lambda().eq(ActivityTurntableJoinLog::getActivityId, con.getActivityId());
            joinLogQw.lambda().in(ActivityTurntableJoinLog::getUserId, userIdList);
            List<ActivityTurntableJoinLog> turntableJoinLogList = iActivityTurntableJoinLogService.list(joinLogQw);
            return turntableJoinLogList.stream()
                    .collect(Collectors.groupingBy(ActivityTurntableJoinLog::getUserId));
        });
        CompletableFuture<Set<Long>> userIdSetFuture = YsThread.execute(() -> {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().in(UserCat::getUserId, userIdList);
            userCatQw.lambda().eq(UserCat::getCatStatus, StatusOldEnum.USER_CAT_TAKE.getStatus());
            List<UserCat> userCatList = iUserCatService.list(userCatQw);
            return userCatList.stream().map(UserCat::getUserId).collect(Collectors.toSet());
        });
        List<ActivityTurntableWinnerUserVO> results = new ArrayList<>();
        Map<Long, List<ActivityTurntableJoinLog>> joinLogMap = joinLogMapFuture.join();
        Set<Long> userIdSet = userIdSetFuture.join();
        for (User record : records) {
            ActivityTurntableWinnerUserVO vo = new ActivityTurntableWinnerUserVO();
            vo.setUserId(record.getId());
            vo.setPetNickName(record.getNickName());
            vo.setPic(record.getAvatar());
            List<ActivityTurntableJoinLog> joinLogList = joinLogMap.get(record.getId());
            vo.setJoinNum(joinLogList.size());
            List<ActivityTurnableRedeemRecord> redeemRecords = redeemRecordMap.get(record.getId());
            vo.setWinnerNum(redeemRecords.size());
            vo.setActivityId(con.getActivityId());
            vo.setIsTakeCat(userIdSet.contains(record.getId()) ? EnableEnum.YES.getEnable() : EnableEnum.NO.getEnable());
            results.add(vo);
        }
        return new PageDTO<>(page.getCurrent(), page.getTotal(), results);
    }


    public PageDTO<ActivityTurntablePhysicalRedeemVO> getActivityTurntablePhysicalRedeemPage(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntablePhysicalRedeemPage con) {
        QueryWrapper<ActivityTurnableRedeemRecord> redeemRecordQw = new QueryWrapper<>();
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getActivityId, con.getActivityId());
        if (StringUtils.isNotBlank(con.getSendStatus())) {
            redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getSendStatus, con.getSendStatus());
        }
        if (Objects.nonNull(con.getUserId())) {
            redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getUserId, con.getUserId());
        }
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getType, EnableEnum.YES.getEnable());
        redeemRecordQw.lambda().orderByDesc(ActivityTurnableRedeemRecord::getRedeemTime);
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getRedeemStatus, ActivityTurnableRedeemRecord.Enums.ISSUED.name());
        Page<ActivityTurnableRedeemRecord> page = iActivityTurnableRedeemRecordService.page(new Page<>(con.getCurrent(), con.getSize()), redeemRecordQw);
        List<ActivityTurnableRedeemRecord> records = page.getRecords();
        if (records.isEmpty()) {
            return new PageDTO<>(page.getCurrent(), page.getTotal(), new ArrayList<>());
        }
        ArrayList<ActivityTurntablePhysicalRedeemVO> results = new ArrayList<>();
        for (ActivityTurnableRedeemRecord record : records) {
            ActivityTurntablePhysicalRedeemVO vo = new ActivityTurntablePhysicalRedeemVO();
            vo.setId(record.getId());
            vo.setNo("SWDH" + DateUtil.dateTimeFormatter(record.getRedeemTime(), "yyyyMMddHHmmss"));
            vo.setGoodsName(record.getGoodsName());
            ActivityTurntablePrized activityTurntablePrized = record.getActivityTurntablePrized();
            vo.setNum(activityTurntablePrized.getQuantityPerPrize().toString());
            vo.setUserId(record.getUserId());
            vo.setSendStatus(record.getSendStatus());
            vo.setGoodsPic(record.getGoodsPic());
            if (StringUtils.isNotBlank(record.getDeliveryPhone()) && StringUtils.isNotBlank(record.getDeliveryName())) {
                vo.setAddress(record.getDeliveryInfo());
            }
            vo.setRemark(record.getRemark());
            results.add(vo);
        }
        return new PageDTO<>(page.getCurrent(), page.getTotal(), results);
    }

    public List<ActivityTurntableUserWinnerPrizedInfo> getActivityTurntableUserWinnerPrizedInfo(Long activityId, Long userId) {
        QueryWrapper<ActivityTurnableRedeemRecord> redeemRecordQw = new QueryWrapper<>();
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getActivityId, activityId);
        redeemRecordQw.lambda().eq(ActivityTurnableRedeemRecord::getUserId, userId);
        redeemRecordQw.lambda().orderByDesc(ActivityTurnableRedeemRecord::getCreateTime);
        List<ActivityTurnableRedeemRecord> redeemRecordList = iActivityTurnableRedeemRecordService.list(redeemRecordQw);
        if (CollectionUtils.isEmpty(redeemRecordList)) {
            return new ArrayList<>();
        }
        return redeemRecordList.stream().map(redeemRecord -> {
            ActivityTurntableUserWinnerPrizedInfo activityTurntableUserWinnerPrizedInfo = new ActivityTurntableUserWinnerPrizedInfo();
            activityTurntableUserWinnerPrizedInfo.setPrizedName(redeemRecord.getActivityTurntablePrized().getPrizedName());
            activityTurntableUserWinnerPrizedInfo.setWinnerTime(redeemRecord.getCreateTime());
            activityTurntableUserWinnerPrizedInfo.setRedeemStatus(redeemRecord.getRedeemStatus());
            activityTurntableUserWinnerPrizedInfo.setPic(redeemRecord.getActivityTurntablePrized().getPrizedIcon());
            return activityTurntableUserWinnerPrizedInfo;
        }).toList();

    }

    public ActivityTurntablePhysicalSendInfoVO getActivityTurntablePhysicalSendInfo(StageEmpDTO emp, Long redeemRecordId) {
        ActivityTurnableRedeemRecord redeemRecord = iActivityTurnableRedeemRecordService.getById(redeemRecordId);
        if (Objects.isNull(redeemRecord)) {
            throw new YsException(-1, "未找到该奖品");
        }
        ActivityTurntablePhysicalSendInfoVO vo = new ActivityTurntablePhysicalSendInfoVO();
        vo.setId(redeemRecord.getId());
        vo.setGoodsName(redeemRecord.getGoodsName());
        vo.setGoodsPic(redeemRecord.getGoodsPic());
        vo.setWayBillNo(JSONArray.parseArray(redeemRecord.getWaybillNo(), String.class));
        return vo;
    }

    public void physicalSend(StageEmpDTO emp, ActivityTurntableCondition.PhysicalSendCon con) {
        ActivityTurnableRedeemRecord redeemRecord = iActivityTurnableRedeemRecordService.getById(con.getRedeemRecordId());
        if (Objects.isNull(redeemRecord)) {
            throw new YsException(-1, "未找到该奖品");
        }
        redeemRecord.setWaybillNo(JSONArray.toJSONString(con.getWaybillNoList()));
        redeemRecord.setSendStatus(ActivityTurnableRedeemRecord.Enums.SHIPPED.name());
        iActivityTurnableRedeemRecordService.updateById(redeemRecord);
    }


    public List<JSONObject> getActivityTurntablePhysicalFreight(StageEmpDTO emp, Long redeemRecordId) {
        try {
            ActivityTurnableRedeemRecord redeemRecord = iActivityTurnableRedeemRecordService.getById(redeemRecordId);
            if (Objects.isNull(redeemRecord)) {
                throw new YsException(-1, "未找到该奖品");
            }
            if (StringUtils.isBlank(redeemRecord.getWaybillNo())) {
                throw new YsException(-1, "未找到物流信息");
            }
            List<String> wayBillNoList = JSONArray.parseArray(redeemRecord.getWaybillNo(), String.class);
            List<JSONObject> resultList = new ArrayList<>();
            for (String expressId : wayBillNoList) {
                resultList.add(getDeliveryByOrder(expressId, redeemRecord.getDeliveryPhone()));
            }
            return resultList;
        } catch (Exception e) {
            throw new YsException(-1, "查询物流信息失败");
        }


    }


    public String getActivityTurntableRule(ActivityTurnable turnable) {
        StringBuilder rule = new StringBuilder();
        ActivityTurnable.JoinRuleDTO joinRuleDTO = turnable.getJoinRuleDTO();
        if (joinRuleDTO.getType().equals(ActivityTurnable.Enums.ALL_USER_DAY_NUM.name())) {
            ActivityTurnable.Siphon first = joinRuleDTO.getSiphonList().getFirst();
            rule = new StringBuilder("抽奖配置：" + "每人每天可参与" + first.getNum() + "次抽奖（活动期间内）");
        }
        if (joinRuleDTO.getType().equals(ActivityTurnable.Enums.ADOPT_AND_NOT_ADOPT_USER_NUM.name())) {
            for (ActivityTurnable.Siphon siphon : joinRuleDTO.getSiphonList()) {
                if (siphon.getType().equals(ActivityTurnable.Enums.ADOPT.name())) {
                    rule = new StringBuilder("抽奖配置：" + "接宠(未退)用户每人每天可参与" + siphon.getNum() + "次抽奖 ");
                }
                if (siphon.getType().equals(ActivityTurnable.Enums.NOT_ADOPT.name())) {
                    rule.append("未接宠(含退宠、直购)用户每人每天可参与").append(siphon.getNum()).append("次抽奖，未领宠(活动期间内)");
                }
            }
        }
        if (joinRuleDTO.getType().equals(ActivityTurnable.Enums.ALL_USER_TOTAL_NUM.name())) {
            ActivityTurnable.Siphon first = joinRuleDTO.getSiphonList().getFirst();
            rule = new StringBuilder("抽奖配置：每人总共可参与" + first.getNum() + "次抽奖（活动期间内）");
        }
        rule.append(System.lineSeparator());
        ActivityTurnable.RedeemRuleDTO redeemRuleDTO = turnable.getRedeemRuleDTO();
        if (redeemRuleDTO.getType().equals(ActivityTurnable.Enums.NO_OVER_TIME.name())) {
            rule.append("中奖领取配置：无时间限制（可通过活动页面直接兑换）");
        }
        if (redeemRuleDTO.getType().equals(ActivityTurnable.Enums.ACTIVITY_END_OVER_TIME.name())) {
            rule.append("中奖领取配置：在活动结束时间之前可兑奖");
        }
        if (redeemRuleDTO.getType().equals(ActivityTurnable.Enums.WINNER_HOUR_OVER_TIME.name())) {
            rule.append("中奖领取配置：" + "中奖后").append(redeemRuleDTO.getHour()).append("小时内完成兑奖（超过兑奖时间将过期无法兑换）");
        }
        return rule.toString();
    }


    /**
     * 设置抽奖规则
     *
     * @param con      请求参数
     * @param turnable 转盘对象
     */
    public void setRule(ActivityTurntableCondition.AddOrUpdateActivityTurntableCon con,
                        ActivityTurnable turnable) {
        //设置抽奖次数规则
        ActivityTurnable.JoinRuleDTO joinRuleDTO = getJoinRuleDTO(con);
        turnable.setJoinRule(JSONObject.toJSONString(joinRuleDTO));

        //设置中奖领取规则
        ActivityTurnable.RedeemRuleDTO redeemRuleDTO = new ActivityTurnable.RedeemRuleDTO();
        ActivityTurntableCondition.RedeemRule redeemRule = con.getRedeemRule();
        redeemRuleDTO.setType(redeemRule.getType());
        redeemRuleDTO.setHour(redeemRule.getHour());
        turnable.setRedeemRule(JSONObject.toJSONString(redeemRuleDTO));
    }

    private ActivityTurnable.JoinRuleDTO getJoinRuleDTO(ActivityTurntableCondition.AddOrUpdateActivityTurntableCon con) {
        ActivityTurnable.JoinRuleDTO joinRuleDTO = new ActivityTurnable.JoinRuleDTO();
        ActivityTurntableCondition.JoinRule joinRule = con.getJoinRule();
        joinRuleDTO.setType(joinRule.getType());
        List<ActivityTurntableCondition.Siphon> siphonList = joinRule.getSiphonList();
        ArrayList<ActivityTurnable.Siphon> siphons = new ArrayList<>();
        for (ActivityTurntableCondition.Siphon siphonCon : siphonList) {
            ActivityTurnable.Siphon siphon = new ActivityTurnable.Siphon();
            siphon.setType(siphonCon.getType());
            siphon.setNum(siphonCon.getNum());
            siphons.add(siphon);
        }
        joinRuleDTO.setSiphonList(siphons);
        return joinRuleDTO;
    }

    /**
     * 设置奖品
     *
     * @param con      请求参数
     * @param turnable 转盘对象
     */
    public void setActivityTurntablePrized(ActivityTurntableCondition.AddOrUpdateActivityTurntableCon con,
                                           ActivityTurnable turnable) {
        List<ActivityTurntableCondition.ActivityTurntablePrized> activityTurntablePrizedConList = con.getActivityTurntablePrizedList();
        if (CollectionUtils.isEmpty(activityTurntablePrizedConList)) {
            throw new YsException(-1, "请添加奖品");
        }
        //移除所有该转盘下的所有奖品
        QueryWrapper<ActivityTurntablePrized> prizedQw = new QueryWrapper<>();
        prizedQw.lambda().eq(ActivityTurntablePrized::getActivityId, turnable.getId());
        List<ActivityTurntablePrized> prizedList = iActivityTurntablePrizedService.list(prizedQw);
        for (ActivityTurntablePrized activityTurntablePrized : prizedList) {
            redisTemplateLong.delete(MessageFormat.format(RedisKey.Enums.ACTIVITY_TURNTABLE_PRIZED_KEY.getKey(), activityTurntablePrized.getId()));
        }

        iActivityTurntablePrizedService.remove(prizedQw);
        //添加奖品
        ArrayList<ActivityTurntablePrized> activityTurntablePrizedList = new ArrayList<>();
        for (ActivityTurntableCondition.ActivityTurntablePrized activityTurntablePrizedCon : activityTurntablePrizedConList) {
            ActivityTurntablePrized activityTurntablePrized = new ActivityTurntablePrized();
            activityTurntablePrized.setActivityId(turnable.getId());
            BeanUtils.copyProperties(activityTurntablePrizedCon, activityTurntablePrized);
            if (activityTurntablePrizedCon.getType().equals(ActivityTurntablePrized.Enums.YS_MONEY.name())) {
                activityTurntablePrized.setQuantityPerPrize(MoneyUtil.str2Long(activityTurntablePrizedCon.getQuantityPerPrize()));
                activityTurntablePrized.setTotal(MoneyUtil.str2Long(activityTurntablePrizedCon.getTotal()));
            } else {
                activityTurntablePrized.setQuantityPerPrize(Long.parseLong(activityTurntablePrizedCon.getQuantityPerPrize()));
                activityTurntablePrized.setTotal(Long.parseLong(activityTurntablePrizedCon.getTotal()));
            }
            activityTurntablePrizedList.add(activityTurntablePrized);
        }
        iActivityTurntablePrizedService.saveBatch(activityTurntablePrizedList);
        for (ActivityTurntablePrized prized : activityTurntablePrizedList) {
            if (prized.getType().equals(ActivityTurntablePrized.Enums.NOT_PRIZED.name())) {
                continue;
            }
            redisTemplateLong.opsForValue().set(MessageFormat.format(RedisKey.Enums.ACTIVITY_TURNTABLE_PRIZED_KEY.getKey(), prized.getId()),
                    prized.getTotal());
        }

    }


    private JSONObject getDeliveryByOrder(String expressId, String phone) throws Exception {
        String baseUrl = "https://wdexpress.market.alicloudapi.com/gxali";

        String nValue = expressId + ":" + phone.substring(7);
        String encodedN = URLEncoder.encode(nValue, StandardCharsets.UTF_8);

        String urlStr = baseUrl + "?n=" + encodedN;

        URL url = new URL(urlStr);
        HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
        httpCon.setRequestMethod("GET");
        httpCon.setRequestProperty("Authorization", "APPCODE " + freightAppId);
        httpCon.setConnectTimeout(5000);
        httpCon.setReadTimeout(5000);

        int httpCode = httpCon.getResponseCode();
        if (httpCode == HttpURLConnection.HTTP_OK) {
            try (InputStream in = httpCon.getInputStream()) {
                String json = IoUtil.read(in, StandardCharsets.UTF_8);
                return JSONObject.parseObject(json);
            }
        } else {
            throw new YsException(-1, "查询订单物流错误，HTTP code: " + httpCode);
        }
    }


    public ActivityTurntablePhysicalGoodsInfo getActivityTurntablePhysicalGoodsInfo(StageEmpDTO emp, Long prizedId) {
        if (Objects.isNull(prizedId)) {
            return null;
        }
        GoodsSpecs goodsSpecs = iGoodsSpecsService.getById(prizedId);
        Goods goods = iGoodsService.getById(goodsSpecs.getGoodsId());
        OrderGoods.KeyValueDTO first = JSONArray.parseArray(goodsSpecs.getGoodsSpecs(), OrderGoods.KeyValueDTO.class).getFirst();
        return new ActivityTurntablePhysicalGoodsInfo()
                .setGoodsName(goods.getGoodsName())
                .setGoodsSpec(first.getValue());
    }


    /**
     * 获取中奖信息 EXCEL
     *
     * @param emp 员工信息
     * @param con 请求参数
     */
    public void getActivityTurntableJoinUserPageExcel(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntableJoinUserPage con, HttpServletResponse response) throws IOException {
        con.setCurrent(1);
        con.setSize(10000);
        PageDTO<ActivityTurntableJoinUserVO> activityTurntableJoinUserPage = getActivityTurntableJoinUserPage(emp, con);
        List<ActivityTurntableJoinUserVO> records = activityTurntableJoinUserPage.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return;
        }
        List<Long> userIdList = records.stream().map(ActivityTurntableJoinUserVO::getUserId).toList();
        QueryWrapper<User> userQw = new QueryWrapper<>();
        userQw.lambda().eq(User::getId, userIdList);
        Map<Long, User> userMap = iUserService.list(userQw).stream().collect(Collectors.toMap(User::getId, it -> it));
        ArrayList<ActivityTurntableJoinPageExcelDTO> dtoList = new ArrayList<>();
        for (ActivityTurntableJoinUserVO vo : records) {
            ActivityTurntableJoinPageExcelDTO dto = new ActivityTurntableJoinPageExcelDTO();
            BeanUtils.copyProperties(vo, dto);
            User user = userMap.get(vo.getUserId());
            if (Objects.isNull(user)) {
                dto.setUserPhone("");
                dtoList.add(dto);
                continue;
            }
            dto.setUserPhone(user.getPhone());
            dtoList.add(dto);
        }
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyExcel没有关系
        String fileName = Objects.requireNonNull(DateUtil.localDateTimeFormat(LocalDateTime.now()))
                .replaceAll("-", "").replaceAll("/", "").replaceAll(":", "")
                .replaceAll(" ", "");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ActivityTurntableJoinPageExcelDTO.class).sheet("出仓统计数据")
                .doWrite(dtoList);

    }

    /**
     * 获取中奖信息 EXCEL
     *
     * @param emp 员工信息
     * @param con 请求参数
     */
    public void getActivityTurntableWinnerPageExcel(StageEmpDTO emp, ActivityTurntableCondition.GetActivityTurntableWinnerPage con, HttpServletResponse response) throws IOException {
        con.setCurrent(1);
        con.setSize(10000);
        PageDTO<ActivityTurntableWinnerUserVO> activityTurntableWinnerPage = getActivityTurntableWinnerPage(emp, con);
        if (ObjectUtils.isEmpty(activityTurntableWinnerPage.getRecords())) {
            return;
        }
        List<Long> userIdList = activityTurntableWinnerPage.getRecords().stream().map(ActivityTurntableWinnerUserVO::getUserId).toList();
        QueryWrapper<User> userQw = new QueryWrapper<>();
        userQw.lambda().eq(User::getId, userIdList);
        Map<Long, User> userMap = iUserService.list(userQw).stream().collect(Collectors.toMap(User::getId, it -> it));
        ArrayList<ActivityTurntableJoinPageExcelDTO> dtoList = new ArrayList<>();
        for (ActivityTurntableWinnerUserVO vo : activityTurntableWinnerPage.getRecords()) {
            ActivityTurntableJoinPageExcelDTO dto = new ActivityTurntableJoinPageExcelDTO();
            BeanUtils.copyProperties(vo, dto);
            User user = userMap.get(vo.getUserId());
            if (Objects.isNull(user)) {
                dto.setUserPhone("");
                dtoList.add(dto);
                continue;
            }
            dto.setUserPhone(user.getPhone());
            dto.setPetNickName(user.getNickName());
            dtoList.add(dto);
        }
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = Objects.requireNonNull(DateUtil.localDateTimeFormat(LocalDateTime.now())).replaceAll("-", "").replaceAll("/", "").replaceAll(":", "").replaceAll(" ", "");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ActivityTurntableJoinPageExcelDTO.class).sheet("数据").doWrite(dtoList);
    }
}



